﻿namespace Raven
{
    public abstract class Trigger<entity_type> : BaseGameEntity
    {
        //Every trigger owns a trigger region. If an entity comes within this 
        //region the trigger is activated
        private TriggerRegion _regionOfInfluence;
        private bool _removeFromGame;
        private bool _active;
        private int _graphNodeIndex;

        protected void SetGraphNodeIndex(int idx)
        {
            _graphNodeIndex = idx;
        }

        protected void SetToBeRemovedFromGame()
        {
            _removeFromGame = true;
        }

        protected void SetInactive()
        {
            _active = false;
        }

        protected void SetActive()
        {
            _active = true;
        }

        //returns true if the entity given by a position and bounding radius is
        //overlapping the trigger region
        protected bool isTouchingTrigger(Vector2 EntityPos, Fix EntityRadius)
        {
            if (_regionOfInfluence != null)
            {
                return _regionOfInfluence.isTouching(EntityPos, EntityRadius);
            }

            return false;
        }

        //child classes use one of these methods to initialize the trigger region
        protected void AddCircularTriggerRegion(Vector2 center, Fix radius)
        {
            _regionOfInfluence = new TriggerRegionCircle(center, radius);
        }

        protected void AddRectangularTriggerRegion(Vector2 topLeft, Vector2 bottomRight)
        {
            _regionOfInfluence = new TriggerRegionRectange(topLeft, bottomRight);
        }

        public override void Destroy()
        {
            throw new System.NotImplementedException();
        }

        public Trigger(EntityType type) : base(type)
        {
            _removeFromGame = false;
            _active = true;
            _graphNodeIndex = Constants.INVALID_NODE_INDEX;
            _regionOfInfluence = null;
        }

        //when this is called the trigger determines if the entity is within the
        //trigger's region of influence. If it is then the trigger will be 
        //triggered and the appropriate action will be taken.
        public abstract void Try(entity_type entity);

        //called each update-step of the game. This methods updates any internal
        //state the trigger may have
        public abstract void Update();

        public int GraphNodeIndex()
        {
            return _graphNodeIndex;
        }

        public bool isToBeRemoved()
        {
            return _removeFromGame;
        }

        public bool isActive()
        {
            return _active;
        }
    }
}